這篇繼續介紹生命週期的另外兩個階段: Updating & Unmounting,以及了解元件在各個生命週期中更新 DOM 的兩個階段 Render Phase & Commit Phase。
Updating 階段總共有六個,以下詳細介紹:
請見上篇介紹。
shouldComponentUpdate(newProps, newState)
它接收了兩個參數,分別是新的 props 和 state,而這個函式的作用可以從名字就知道,可以用來控制是不是要讓元件做更新,可以用它來做效能優化。
這個函式最後回傳的是一個 boolean 值,如果是 true 就進入到 render 函式,false 就不會往以下的 life cycle 階段進行(不會更新元件)
。若沒實作 shouldComponentUpdate() 預設會返回 true。
另外還要注意 shouldComponentUpdate() 它在更新 props 和 state 時會呼叫,但如果是透過 forceUpdate() 更新元件就不會呼叫 shouldComponentUpdate()。
請見上篇介紹。
getSnapshotBeforeUpdate(prevProps, prevState)
這個函式在元件實際渲染前被呼叫,接收的兩個參數分別是修改前的 props 和 state,用來取得元件 DOM 被修改前的一些資訊。
getSnapshotBeforeUpdate 被執行後的回傳值會被傳進 componentDidUpdate 的第三個參數。
這個函式不常使用。
元件剛剛更新完畢時呼叫,componentDidUpdate(prevProps, prevState, snapshot)
總共可以傳入三個參數,分別是更新前的 props、state 和 getSnapshotBeforeUpdate 的回傳值。
它可以用在元件更新後對應的後續動作,例如比對新props/state 和舊 props/state 的差異,存取 DOM、呼叫 api 等。
若要在 componentDidUpdate() 內去使用 setState,記得要加上條件判斷,否則一直更新 state 一直導致元件重新渲染會造成無窮迴圈。
最後是元件移除的階段,不過也就只有一個函式-componentWillUnmount()。
這個元件作用是將一些用不到的 request、event listeners、setTimeout 移除,等於 useEffect cleanup 的作用。
範例:
componentWillUnmount() {
clearInterval(this.interval);
}
在 React life cycle 裡也有內建的錯誤處理函式,有錯誤發生時可以使用它們。
static getDerivedStateFromError(error)
這個函式為一個靜態方法,主要是用來更新 state,讓錯誤畫面出現。
記得不能在這裡處理 side effect,並且只能回傳更新的 state 或 null。
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info)
這個函式可以捕捉從子元件中拋出的錯誤,並將這個錯誤訊息提供給 Error Boundary 元件。
這個函式就可以處理 side effect。
中文可以翻譯成"錯誤邊界",這個名詞的概念是說如果某個元件發生錯誤時,包覆該元件的 Error Boundary 元件可以把錯誤訊息呈現在網頁上,並避免影響其它的父元件。
所以還是要用 try catch 來處理無法被 Error Boundary 捕捉的錯誤。
<ErrorBoundary>
<OtherComponent />
</ErrorBoundary>
class ErrorBoundary extends Component {
state = { errorMessage: null };
static getDerivedStateFromError(error) {
// update state
return { errorMessage: error.message };
}
componentDidCatch(error, info) {
console.log(error, info);
}
render() {
if (this.state.errorMessage) {
return <h1>{this.state.errorMessage}</h1>;
}
return this.props.children;
}
}
最後介紹的是圖片中左側的 Render Phase、Commit Phase,詳細說的話兩個階段中間還有一個 Pre-Commit Phase。
React 在此階段時會透過 render 函式將 JSX 做轉換並生成新的 Virtual DOM ,然後和舊的 Real DOM 做比較(Diff),決定出哪些部分要實際更新到 DOM 元素上。
注意: 此階段不建議操作 ref
這個階段屬於非同步,不能有 side effect,並且可以被暫停、中斷、重新開始,因此這個階段包含的建立 constructor、shouldComponentUpdate、render 等函式都必須是純粹函式。
這個階段發生在 React 要把 React element 加到 DOM 的前一刻,可以讀取 DOM。
屬於同步,不能被中斷的階段,會將要更新的 Virtual DOM 更新到實際的 DOM 元素,可以進行 side effect 的操作。
注意: 此階段才操作 ref 比較好
React lifecycle methods: An approachable tutorial with examples
React 元件生命週期 (Component Lifecycle)
I Want To Know React - Lifecycle 階段